#include "./make_ice_task.h"
#include "../ice_driver/ctrl.h"
#include "../ice_driver/sensor.h"
#include "../utils/log.h"

namespace ice_task {

using namespace ice_driver;

MakeIceTask makeIceTask;

constexpr uint16_t MIN_STIR_SPEED = 0;
constexpr uint32_t STIR_SPEED_FAIL_DURATION = 60 * 1000;
constexpr uint32_t COMPR_OPEN_CLOSE_DELAY = 3 * 60 * 1000;

static uint32_t comprCloseTick = 0;
static void close_compr() {
    ctrl.close(Ctrl::Parts::COMPR);
    comprCloseTick = osKernelGetTickCount();
}

void MakeIceTask::init_start() {
    m_mq.init();
    m_flags.init();
    start();
}

void MakeIceTask::run() {
    
    for (;;) {
        switch (m_state) {
            case State::IDLE: do_idle(); break;
            case State::WORK_BEGIN: do_work_begin(); break;
            case State::WORK: do_work(); break;
            case State::WORK_END: do_work_end(); break;
            case State::STOP: do_stop(); break;
            case State::FAIL:
            case State::TIMEOUT: do_timeout(); break;
            case State::STIR: do_stir(); break;
        }
    }
}

void MakeIceTask::do_stir() {
    constexpr uint32_t STIR_TIME = 20 * 1000;
    ctrl.stir_motor_open();
    if (!wait(STIR_TIME)) {
        m_state = State::IDLE;
    }
    ctrl.stir_motor_close();
}

void MakeIceTask::do_idle() {
    constexpr uint32_t STIR_INTERVAL_TIME = 30 * 60 * 1000;

    uint32_t cond_count = 0;
    uint32_t time_count = 0;

    for (;;) {
        if (sensor.is_bucket_low() && 
           (!sensor.is_ice_full())) 
        {
            cond_count ++;
            if (cond_count >= 5) {
                m_state = State::WORK_BEGIN;
                break;
            }
        } else {
            cond_count = 0;
            time_count += 500;
            if (time_count >= STIR_INTERVAL_TIME) {
                m_state = State::STIR;
                break;
            }
        }

        if (wait(500)) {
            break;
        }
    }
}

void MakeIceTask::do_work_begin() {
    uint32_t tick = comprCloseTick + COMPR_OPEN_CLOSE_DELAY;
    uint32_t cur = osKernelGetTickCount() + m_stir_compr_delay;
    if (cur < tick) {
        if (wait(tick - cur)) {
            return;
        }
    }

    ctrl.stir_motor_open();
    if (wait(m_stir_compr_delay)) {
        ctrl.stir_motor_close();
        return;
    }
    ctrl.stir_motor_close();
    m_state = State::WORK;
}

void MakeIceTask::do_work() {

    uint32_t cond_count = 0;
    uint32_t time_count = 0;
    uint32_t fail_count = 0;
    uint32_t low_count = 0;
    ctrl.open(Ctrl::Parts::COMPR);
    ctrl.open(Ctrl::Parts::FAN);
    ctrl.stir_motor_open();

    for (;;) {
        if (!sensor.is_bucket_low()) {
            low_count ++;
            m_state = State::IDLE;
            println("低水位检测不到");
            break;
        } else {
            low_count = 0;
        }

        if (sensor.stir_speed() < MIN_STIR_SPEED) {
            fail_count += 1000;
            if (fail_count >= STIR_SPEED_FAIL_DURATION) {
                m_state = State::FAIL;
                break;
            }
        } else {
            fail_count = 0;
        }

        if (sensor.is_ice_full()) {
            cond_count ++;
            if (cond_count >= 20) {
                m_state = State::WORK_END;
                m_stir_compr_delay = RUN_STIR_COMPR_DELAY;
                break;
            }
        } else {
            cond_count = 0;
        }

        if (wait(1000)) {
            break;
        }

        time_count += 1000;
        if (time_count >= MAKE_ICE_TIMEOUT) {
            m_state = State::TIMEOUT;
            break;
        }
    }
    ctrl.stir_motor_close();
    ctrl.close(Ctrl::Parts::FAN);
    close_compr();
}

void MakeIceTask::do_work_end() {
    ctrl.stir_motor_open();
    if (wait(STOP_STIR_COMPR_DELAY)) {
        ctrl.stir_motor_close();
        return;
    }
    ctrl.stir_motor_close();
    m_state = State::IDLE;
}

void MakeIceTask::do_timeout() {
    wait();
}

void MakeIceTask::do_stop() {
    m_flags.set_flags(FLAG_STOP);
    wait();
}

}
